package com.zzf.concurrent.example.atomic;

import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author GaoFeng2017
 * @date 2019/9/11 16:58
 */
@Slf4j
public class AtomicIntegerTest {

    private static volatile int count;
    private static Set<Integer> set = Collections.synchronizedSet(new HashSet<>());
    private static AtomicInteger atomicInteger = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        // volatileExample();
        // atomicIntegerTest();
        atomicIntegerApi();
    }

    private static void volatileExample() throws InterruptedException {

        Thread t1 = new Thread(() -> {
            int x = 0;
            while (x < 500) {
                set.add(count);
                log.info("count is increment -> {}", count);
                x++;
                count++;
            }
        });

        Thread t2 = new Thread(() -> {
            int x = 0;
            while (x < 500) {
                set.add(count);
                log.info("count is increment -> {}", count);
                x++;
                count++;
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        log.info("set size -> {}", set.size());

    }

    private static void atomicIntegerTest() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            int x = 0;
            while (x < 500) {
                int temp = atomicInteger.getAndIncrement();
                set.add(temp);
                log.info("atomic integer is increment -> {}", temp);
                x++;
            }
        });

        Thread t2 = new Thread(() -> {
            int x = 0;
            while (x < 500) {
                int temp = atomicInteger.getAndIncrement();
                set.add(temp);
                log.info("atomic integer is increment -> {}", temp);
                x++;
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        log.info("set size -> {}", set.size());
    }

    private static void atomicIntegerApi() {

        // value已使用volatile关键字

        // 无参数构造函数，value为0
        AtomicInteger normalInteger = new AtomicInteger();
        // 有参构造函数，初始化value为参数的值
        AtomicInteger customInteger = new AtomicInteger(10);

        // 获取value
        int customValue = customInteger.get();
        log.info("customValue -> {}", customValue);

        // 先获取再添加指定值，无锁的线程安全的操作
        int valueAfterAdd = customInteger.getAndAdd(10);
        log.info("value after add -> {}", valueAfterAdd);

        // 先自增再获取，同上
        int valueGetAndIncrement = customInteger.incrementAndGet();
        log.info("valueGetAndIncrement -> {}", valueGetAndIncrement);

        // ...

    }
}
